package com.example.goodog;

import java.io.IOException;
import java.util.List;

import android.app.AlertDialog;
import android.app.Service;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.location.Address;
import android.location.Geocoder;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.IBinder;
import android.provider.Settings;

import com.example.goodog.interfaces.LocationFoundCallback;


public class GPSTracker extends Service implements LocationListener {

	private final Context mContext;
	
	public LocationFoundCallback callback;

	// flag for GPS status
	boolean isGPSEnabled = false;

	// flag for network status
	boolean isNetworkEnabled = false;

	boolean canGetLocation = false;
	Location location; // location
	double latitude; // latitude
	double longitude; // longitude

	//private Criteria criteria;
	//private String provider;

	// The minimum distance to change Updates in meters
	private static final long MIN_DISTANCE_CHANGE_FOR_UPDATES = 10; // 10 meters

	// The minimum time between updates in milliseconds
	private static final long MIN_TIME_BW_UPDATES = 1000 * 60 * 1; // 1 minute

	// Declaring a Location Manager
	protected LocationManager locationManager;

	public GPSTracker(Context context) {
		this.mContext = context;
		StartgetLocationManager();
	}

	public void StartgetLocationManager() {
		try {
			
			//criteria = new Criteria();
			//criteria.setAccuracy(Criteria.ACCURACY_FINE);
			//provider = locationManager.getBestProvider(criteria, true);

			locationManager = (LocationManager) mContext.getSystemService(LOCATION_SERVICE);

			// getting GPS status
			isGPSEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);

			// getting network status
			isNetworkEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);

			if (!isGPSEnabled && !isNetworkEnabled)
			{
				// no network provider is enabled
			} 
			else 
			{
				this.canGetLocation = true;
				// First get location from Network Provider
				if (isNetworkEnabled) {
					locationManager.requestLocationUpdates(
							LocationManager.NETWORK_PROVIDER,
							MIN_TIME_BW_UPDATES,
							MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
					if (locationManager != null)
					{
						locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
					}
				}
				// if GPS Enabled get lat/long using GPS Services
				if (isGPSEnabled) {
					locationManager.requestLocationUpdates(
							LocationManager.GPS_PROVIDER,
							MIN_TIME_BW_UPDATES,
							MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
					if (locationManager != null)
					{
						locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
					}
				}
			}

			//setMostRecentLocation(locationManager.getLastKnownLocation(provider));

		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	//private void setMostRecentLocation(Location lastKnownLocation) {}

	@Override
	public void onLocationChanged(Location i_location) {
		// TODO Auto-generated method stub
		if( (i_location.hasAccuracy() && 20 >= i_location.getAccuracy()) ||
			(!isGPSEnabled && i_location.hasAccuracy() && 150 >= i_location.getAccuracy()) )
		{
			location = i_location;
			latitude = i_location.getLatitude();
			longitude = i_location.getLongitude();
			stopUsingGPS();
			callback.callbackCall();
		}		
	}

	@Override
	public void onProviderDisabled(String arg0) {
		// TODO Auto-generated method stub

	}

	@Override
	public void onProviderEnabled(String arg0) {
		// TODO Auto-generated method stub

	}

	@Override
	public void onStatusChanged(String arg0, int arg1, Bundle arg2) {
		// TODO Auto-generated method stub

	}

	@Override
	public IBinder onBind(Intent arg0) {
		// TODO Auto-generated method stub
		return null;
	}

	public double getLatitude(){
		if(location != null){
			latitude = location.getLatitude();
		}

		// return latitude
		return latitude;
	}

	/**
	 * Function to get longitude
	 * */
	public double getLongitude(){
		if(location != null){
			longitude = location.getLongitude();
		}

		// return longitude
		return longitude;
	}

	public Address getAdress(Context context){
		if(location != null){
			longitude = location.getLongitude();
			latitude = location.getLatitude();
			List<Address> addresses;
			try {
				addresses = new Geocoder(context).getFromLocation(latitude, longitude, 1);
				if(addresses != null && addresses.size()>0)
				{
					return addresses.get(0);
				}
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}  
		}

		return null;
	}
	
	public float getAccuracy(){
		if(location != null)
		{
			if(location.hasAccuracy())
			{
				return location.getAccuracy();
			}
		}
		return -1;
	}
	
	public static Address getAdress(Context context, double longitude, double latitude){

		List<Address> addresses;
		try {
			addresses = new Geocoder(context).getFromLocation(latitude, longitude, 1);
			if(addresses != null && addresses.size()>0)
			{
				return addresses.get(0);
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}  


		return null;
	}



	/**
	 * Function to check if best network provider
	 * @return boolean
	 * */
	public boolean canGetLocation() {
		return this.canGetLocation;
	}

	/**
	 * Function to show settings alert dialog
	 * */
	public void showSettingsAlert(){
		AlertDialog.Builder alertDialog = new AlertDialog.Builder(mContext);

		// Setting Dialog Title
		alertDialog.setTitle("GPS is settings");

		// Setting Dialog Message
		alertDialog.setMessage("GPS is not enabled. Do you want to go to settings menu?");

		// Setting Icon to Dialog
		//alertDialog.setIcon(R.drawable.delete);

		// On pressing Settings button
		alertDialog.setPositiveButton("Settings", new DialogInterface.OnClickListener() {
			public void onClick(DialogInterface dialog,int which) {
				Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
				mContext.startActivity(intent);
			}
		});

		// on pressing cancel button
		alertDialog.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
			public void onClick(DialogInterface dialog, int which) {
				dialog.cancel();
			}
		});

		// Showing Alert Message
		alertDialog.show();


	}


	public void stopUsingGPS(){
		if(locationManager != null){
			locationManager.removeUpdates(this);
		}       
	}
	protected void finalize( ) throws Throwable
	{ 
		stopUsingGPS();
		super.finalize( );
	}

}